import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.File;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

import org.apache.commons.lang.StringUtils;

public class FileProcessorSelectSolution implements FileProcessor{
	public void processFile(String processFolder, String fileName, String desFolder, String historyFolder) {
		BufferedReader reader = null;
		BufferedWriter writer = null;
		try {
			File file = new File(processFolder + File.separator + fileName);
			if (file.isDirectory())
				return;
			reader = new BufferedReader(new FileReader(file));
			writer = new BufferedWriter(new FileWriter(desFolder + File.separator + fileName));
			boolean needDivide = false;
			String line = null;
			while ((line = reader.readLine()) != null) {
				if (StringUtils.isBlank(line)) {
					continue;
				}
				String[] fields = line.split(",", 2);
				// skipping invalid format line
				if (fields.length < 2 && !"900".equals(line)) {
					continue;
				}
				String recordIndicator = fields[0];
				if ("200".equals(recordIndicator)) {
					needDivide = checkUnitsFor200Line(writer, line, fields);
				} else if ("300".equals(recordIndicator)) {
					covert300LineIfNecessary(writer, line, fields, needDivide);
				} else if ("900".equals(recordIndicator)) {
					// end of file processing.
					writeLineIntoFile(writer, line);
					break;
				} else {
					writeLineIntoFile(writer, line);
				}
			}
			writer.close();
			reader.close();
			moveProcessedFile(processFolder, fileName, historyFolder);
		} catch (Exception ex) {
			 LogUtils.getInstance().error(ex,"");
		} finally {
			try {
				if (writer != null)
					writer.close();
				if (reader != null)
					reader.close();
			} catch (IOException e) {
				LogUtils.getInstance().error(e,"");
			}
		}
	}

	/**
	 * @param If there is "WH" or "VARH" in previous 200, divide each energy value by 1000 
	 * @throws Exception
	 */
	private void covert300LineIfNecessary(BufferedWriter writer, String line,
			String[] fields, boolean needDivide) throws Exception {
		String[] nem300Fields = fields[1].split(",", 1000);
		String newLine = null;
		if (needDivide == true && nem300Fields.length > 6) {
			List<String> nem300List = new ArrayList<String>();
			int lastValueIndex = nem300Fields.length - 6;
			// first add the fields before energy values
			newLine = fields[0] + "," + nem300Fields[0] + ",";
			// add values need to divide into the list, start from 1
			for (int i = 1; i <= lastValueIndex; i++) {
				try {
					Double newValue = Double.parseDouble(nem300Fields[i]) / 1000;
					nem300List.add(newValue.toString());
				// for null or empty string
				} catch (Exception ex) {
					nem300List.add(nem300Fields[i]);
				}
			}
			// add other parts into the list
			for (int i = lastValueIndex + 1; i < nem300Fields.length; i++)
				nem300List.add(nem300Fields[i]);
			newLine += toCsvString(nem300List.toArray(new String[0]));
			writeLineIntoFile(writer, newLine);
		} else {
			writeLineIntoFile(writer, line);
		}
	}

	/**
	 * @return whether there is "wh" or "varh", ignore case
	 * @throws IOException
	 */
	private boolean checkUnitsFor200Line(BufferedWriter writer, String line, String[] fields) throws Exception {
		String[] nem200Fields = fields[1].split(",", 1000);
		Boolean needDivide = false;
		if (nem200Fields.length > 6) {
			String uom = nem200Fields[6];
			if (uom.equalsIgnoreCase("WH") || uom.equalsIgnoreCase("VARH")) {
				needDivide = true;
				nem200Fields[6] = "K" + nem200Fields[6];
				line = fields[0] + "," + toCsvString(nem200Fields);
			} else {
				needDivide = false;
			}
		}
		writeLineIntoFile(writer, line);
		return needDivide;
	}

	private void moveProcessedFile(String processFolder,
			String fileNameWithourSuffix, String historyFolder) {
		List<String> fileList = FileUtils.generateFileList(processFolder);
		for(String fileName : fileList) {
			if (fileName.contains(fileNameWithourSuffix))
				FileUtils.moveIntoFolderReplaceExisting(historyFolder, processFolder + File.separator + fileName);
		}
		
	}

	private void writeLineIntoFile(BufferedWriter writer, String line) throws IOException {
		writer.write(line + "\n");	
	}

	private String toCsvString(String[] stringArray) {
		String result = "";
		for (String item : stringArray)
			result += item + ",";
		return result.substring(0, result.length() - 1);
	}
	
	public static void main(String[] args) {
/*		FileProcessorSelectSolution test = new FileProcessorSelectSolution();
		test.processFile(".", "NEM12#13061700001000000#GLOBALM#CMAHN.csv", "postproc");
		test.processFile(".", "NEM12#13061800001000000#GLOBALM#CMAHN.csv", "postproc");
		test.processFile(".", "NEM12#13062400003000000#GLOBALM#BLDALIV.csv", "postproc");*/
		System.out.println("finished processing!");
	} 
}
